package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.WechatPay;
import com.file.bo.WechatPayTran;
import com.file.constant.EfpConstants;
import com.file.constant.ErrorCode;
import com.file.parser.traprange.PDFTableExtractor;
import com.file.util.JsonUtils;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class WechatPayPdfParser extends BasePdfParser {
	
	public ResponseData<String> parseWechatPayPdfToJson(String filePath) {
		log.info("parseWechatPayPdfToJson started, filePath:{}", filePath);
    	String json = null;
    	
    	try {
    		WechatPay wechatPay = parseWechatPayPdf(filePath);
			json = JsonUtils.convertObjectToJson(wechatPay);
		} catch (Exception e) {
			log.error("[OnError]parseWechatPayPdfToJson failed, filePath:{}", filePath, e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}
    	
    	log.info("parseWechatPayPdfToJson completed, filePath:{}", filePath);
    	return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}
	
	
	public WechatPay parseWechatPayPdf(String filePath) {
		WechatPay wechatPay = parseWechatHeader(filePath);
		
		List<WechatPayTran> wechatPayTrans = new ArrayList<WechatPayTran>();
		wechatPayTrans = parseWechatTrans(filePath);
		//wechatPayTrans = parseTrans(filePath);
		
		wechatPay.setWechatPayTrans(wechatPayTrans);
		return wechatPay;
	}

	public WechatPay parseWechatHeader(String filePath) {
		WechatPay wechatPay = new WechatPay();
		String pdfHeaderText = parsePdfHeaderText(filePath);
		pdfHeaderText = pdfHeaderText.substring(0, pdfHeaderText.indexOf("具体交易明细"));
		String number = pdfHeaderText.substring(pdfHeaderText.indexOf("编号：") + 3, pdfHeaderText.indexOf("微信支付交易明细证明"))
				.trim();
		String name = pdfHeaderText.substring(pdfHeaderText.indexOf("兹证明：") + 4, pdfHeaderText.indexOf("(身份证：")).trim();
		String idNumber = pdfHeaderText.substring(pdfHeaderText.indexOf("身份证：") + 4, pdfHeaderText.indexOf(")，在其微信号"))
				.trim();
		String wechatAccount = pdfHeaderText
				.substring(pdfHeaderText.indexOf("在其微信号：") + 6, pdfHeaderText.indexOf("中的交易明细信息如下")).trim();
		String currency = pdfHeaderText.substring(pdfHeaderText.indexOf("币种：") + 3, pdfHeaderText.indexOf("/单位："))
				.trim();
		String unit = pdfHeaderText.substring(pdfHeaderText.indexOf("/单位：") + 4, pdfHeaderText.indexOf("交易明细对应时间段"))
				.trim();
		String transDetailPeriod = pdfHeaderText.substring(pdfHeaderText.indexOf("交易明细对应时间段") + 9).trim();
		wechatPay.setNumber(number);
		wechatPay.setName(name);
		wechatPay.setIdNumber(idNumber);
		wechatPay.setWechatAccount(wechatAccount);
		wechatPay.setCurrency(currency);
		wechatPay.setUnit(unit);
		wechatPay.setTransDetailPeriod(transDetailPeriod);

		return wechatPay;
	}

	public List<WechatPayTran> parseWechatTrans(String filePath) {
		List<WechatPayTran> wechatPayTrans = new ArrayList<WechatPayTran>();

		String transText = parseTransToText(filePath);
		if (Strings.isNullOrEmpty(transText)) {
			return wechatPayTrans;
		}

		List<List<String>> tranFieldsList = parseTransTextToTranFieldsList(transText);

		StringBuilder tranOrderIdSb = new StringBuilder();
		StringBuilder tranDateSb = new StringBuilder();
		StringBuilder tranTypeSb = new StringBuilder();
		StringBuilder incomeOrExpenseSb = new StringBuilder();
		StringBuilder tranMethodSb = new StringBuilder();
		StringBuilder tranAmtSb = new StringBuilder();
		StringBuilder tranConterPartySb = new StringBuilder();
		StringBuilder merchantOrderIdSb = new StringBuilder();
		for (int i = 0; i < tranFieldsList.size(); i++) {
			// 如果这一行是新的交易的第一行文本，则新建一个stringbuilder
			boolean isStartOfNewTran = !Strings.isNullOrEmpty(tranFieldsList.get(i).get(3));
			if (isStartOfNewTran) {
				if (i != 0) {
					WechatPayTran wechatPayTran = new WechatPayTran();
					wechatPayTran.setTranOrderId(tranOrderIdSb.toString());
					wechatPayTran.setTranDate(tranDateSb.toString());
					wechatPayTran.setTranType(tranTypeSb.toString());
					wechatPayTran.setIncomeOrExpense(incomeOrExpenseSb.toString());
					wechatPayTran.setTranMethod(tranMethodSb.toString());
					wechatPayTran.setTranAmt(tranAmtSb.toString());
					wechatPayTran.setTranConterParty(tranConterPartySb.toString());
					wechatPayTran.setMerchantOrderId(merchantOrderIdSb.toString());
					wechatPayTrans.add(wechatPayTran);
				}

				tranOrderIdSb = new StringBuilder();
				tranDateSb = new StringBuilder();
				tranTypeSb = new StringBuilder();
				incomeOrExpenseSb = new StringBuilder();
				tranMethodSb = new StringBuilder();
				tranAmtSb = new StringBuilder();
				tranConterPartySb = new StringBuilder();
				merchantOrderIdSb = new StringBuilder();

				tranOrderIdSb.append(tranFieldsList.get(i).get(0));
				tranDateSb.append(tranFieldsList.get(i).get(1));
				tranDateSb.append(" ");
				tranTypeSb.append(tranFieldsList.get(i).get(2));
				incomeOrExpenseSb.append(tranFieldsList.get(i).get(3));
				tranMethodSb.append(tranFieldsList.get(i).get(4));
				tranAmtSb.append(tranFieldsList.get(i).get(5));
				tranConterPartySb.append(tranFieldsList.get(i).get(6));
				merchantOrderIdSb.append(tranFieldsList.get(i).get(7));
				
				if (i == tranFieldsList.size() - 1) {
					WechatPayTran wechatPayTran = new WechatPayTran();
					wechatPayTran.setTranOrderId(tranOrderIdSb.toString());
					wechatPayTran.setTranDate(tranDateSb.toString());
					wechatPayTran.setTranType(tranTypeSb.toString());
					wechatPayTran.setIncomeOrExpense(incomeOrExpenseSb.toString());
					wechatPayTran.setTranMethod(tranMethodSb.toString());
					wechatPayTran.setTranAmt(tranAmtSb.toString());
					wechatPayTran.setTranConterParty(tranConterPartySb.toString());
					wechatPayTran.setMerchantOrderId(merchantOrderIdSb.toString());
					wechatPayTrans.add(wechatPayTran);
				}

				// 如果这一行不是新的交易的第一行文本，则使用已有的stringbuilder继续拼接
			} else {
				tranOrderIdSb.append(tranFieldsList.get(i).get(0));
				tranDateSb.append(tranFieldsList.get(i).get(1));
				tranTypeSb.append(tranFieldsList.get(i).get(2));
				incomeOrExpenseSb.append(tranFieldsList.get(i).get(3));
				tranMethodSb.append(tranFieldsList.get(i).get(4));
				tranAmtSb.append(tranFieldsList.get(i).get(5));
				tranConterPartySb.append(tranFieldsList.get(i).get(6));
				merchantOrderIdSb.append(tranFieldsList.get(i).get(7));

				if (i == tranFieldsList.size() - 1) {
					WechatPayTran wechatPayTran = new WechatPayTran();
					wechatPayTran.setTranOrderId(tranOrderIdSb.toString());
					wechatPayTran.setTranDate(tranDateSb.toString());
					wechatPayTran.setTranType(tranTypeSb.toString());
					wechatPayTran.setIncomeOrExpense(incomeOrExpenseSb.toString());
					wechatPayTran.setTranMethod(tranMethodSb.toString());
					wechatPayTran.setTranAmt(tranAmtSb.toString());
					wechatPayTran.setTranConterParty(tranConterPartySb.toString());
					wechatPayTran.setMerchantOrderId(merchantOrderIdSb.toString());
					wechatPayTrans.add(wechatPayTran);
				}
			}
		}

		return wechatPayTrans;
	}

	public String parseTransToText(String filePath) {
		PDFTableExtractor extractor = (new PDFTableExtractor()).setSource(filePath);
		int pdfPageNumber = getPdfPageNumber(filePath);
		//去掉第一页的Header，
		int[] skipFirstPageHeaderLinesIndexes = new int[EfpConstants.WECHATPAY_HEADER_LINE_NUMBER];
		for (int i = 0; i < EfpConstants.WECHATPAY_HEADER_LINE_NUMBER; i++) {
			skipFirstPageHeaderLinesIndexes[i] = i;
		}
		extractor.exceptLine(0, skipFirstPageHeaderLinesIndexes);
		
		//去掉最后一页的Footer,两种情况
		int lineNumberInLastPdf = getLineNumberInLastPage(filePath, pdfPageNumber);
		//1.footer文本行完整展现在最后一页PDF,则直接排除最后一页的footer文本行
		if (lineNumberInLastPdf >= EfpConstants.WECHATPAY_FOOTER_LINE_NUMBER) {
			int[] skipLastPageFooterLinesIndexes = new int[EfpConstants.WECHATPAY_FOOTER_LINE_NUMBER];
			for (int j = 0; j < EfpConstants.WECHATPAY_FOOTER_LINE_NUMBER; j++) {
				skipLastPageFooterLinesIndexes[j] = -(j + 1);
			}
			extractor.exceptLine(pdfPageNumber - 1, skipLastPageFooterLinesIndexes);
		} else {
		//2.footer文本行拆分在倒数第一页和倒数第二页，则直接排除最后一页和倒数第二页的WECHAT_FOOTER_LINE_NO-lineNumberInLastPdf
			extractor.exceptPage(pdfPageNumber - 1);
			
			int footerLinesNumberInlastSecondPage = EfpConstants.WECHATPAY_FOOTER_LINE_NUMBER - lineNumberInLastPdf;
			int[] skipLastSecondPageFooterLinesIndexes = new int[footerLinesNumberInlastSecondPage];
			for (int k = 0; k < footerLinesNumberInlastSecondPage; k++) {
				skipLastSecondPageFooterLinesIndexes[k] = -(k + 1);
			}
			extractor.exceptLine(pdfPageNumber - 2, skipLastSecondPageFooterLinesIndexes);
		}
		
		String text = extractPdfToText(extractor);
		return text;
	}

	// tabula方法解析交易(bug：除第一页外，其他页最后一条交易记录会被遗漏)
	/*
	public List<WechatPayTran> parseTrans(String filePath) {
		// 1. 读取文件
		File pdf = new File(filePath);

		// 2. pdfbox读取PDDocument
		PDDocument pdfDocument = null;
		try {
			pdfDocument = PDDocument.load(pdf);
		} catch (IOException e) {
			log.error("[OnError]load pdf to PDDocument from path error.");
			throw new RuntimeException(e);
		}


		// 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
		ObjectExtractor extractor = new ObjectExtractor(pdfDocument);
		NurminenDetectionAlgorithm detectionAlgorithm = new NurminenDetectionAlgorithm();
		Map<Integer, List<Rectangle>> detectedTables = new HashMap<>();

		// 4. 获取每页的PageIterator
		PageIterator pages = extractor.extract();

		// 5. 解析每页的Rectangle(table的位置)
		while (pages.hasNext()) {
			Page page = pages.next();
			List<Rectangle> tablesOnPage = detectionAlgorithm.detect(page);
			if (tablesOnPage.size() > 0) {
				detectedTables.put(new Integer(page.getPageNumber()), tablesOnPage);
			}
		}

		// 6.通过table位置获取表格具体内容
		List<WechatPayTran> res = new ArrayList<>();

		SpreadsheetExtractionAlgorithm bea = new SpreadsheetExtractionAlgorithm();

		// 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
		for (Map.Entry<Integer, List<Rectangle>> entry : detectedTables.entrySet()) {
			Page page = null;
			try {
				page = getPage(filePath, entry.getKey());
			} catch (IOException e) {
				log.error("[OnError]get page by pageNumber from path error.");
				throw new RuntimeException(e);
			}

			// 支付宝默认每页只有一个表格，因此获取第0个rectangle
			Rectangle rectangle = entry.getValue().get(0);
			Page area = page.getArea(rectangle.getTop(), rectangle.getLeft(),rectangle.getBottom(),rectangle.getRight());

			List<Table> table = bea.extract(area);

			// 支付宝默认每页只有一个表格，因此获取第0个table
			Table t = table.get(0);
			System.out.println("page no." + entry.getKey() + "  " + "交易条数： " + t.getRowCount());
			if (entry.getKey() == 2) {
				System.out.printf("test");
			}

			for (int i = 0; i < t.getRowCount(); i++) {
				// 列数不为8，说明pdf格式该变了
				if (t.getColCount() != 8) {
					log.error("[OnError]format invalid.");
				} else {
					// 去掉表头三行数据
					if (t.getCell(i,0).getText(false).contains("交易明细对应时间段")
							|| t.getCell(i,0).getText(false).contains("具体交易明细")
							|| t.getCell(i,0).getText(false).contains("交易单号")) {
						continue;
					}
					WechatPayTran wechatPayTran = new WechatPayTran();

					wechatPayTran.setTranOrderId(t.getCell(i,0).getText(false));
					wechatPayTran.setTranDate(t.getCell(i,1).getText(false));
					wechatPayTran.setTranType(t.getCell(i,2).getText(false));
					wechatPayTran.setIncomeOrExpense(t.getCell(i,3).getText(false));
					wechatPayTran.setTranMethod(t.getCell(i,4).getText(false));
					wechatPayTran.setTranAmt(t.getCell(i,5).getText(false));
					wechatPayTran.setTranConterParty(t.getCell(i,6).getText(false));
					wechatPayTran.setMerchantOrderId(t.getCell(i,7).getText(false));

					res.add(wechatPayTran);
				}
			}
		}
		return res;
	}

	public Page getPage(String path, int pageNumber) throws IOException {
		ObjectExtractor oe = null;
		try {
			PDDocument document = PDDocument.load(new File(path));
			oe = new ObjectExtractor(document);
			Page page = oe.extract(pageNumber);
			return page;
		} finally {
			if (oe != null)
				oe.close();
		}
	}
	 */
	
	public static void main(String[] args) throws IOException {
		String pdfFilePath = "E:\\data\\file\\微信支付交易明细证明(20201019-20210119).pdf";
		String jsonFilePath = "E:\\data\\file\\微信支付交易明细证明(20201019-20210119).json";
        File jsonFile = new File(jsonFilePath);

        WechatPayPdfParser wechatPayPdfParser = new WechatPayPdfParser();
        ResponseData<String> responseData = wechatPayPdfParser.parseWechatPayPdfToJson(pdfFilePath);
        log.info(responseData.getData());
        FileUtils.write(jsonFile, responseData.getData(), EfpConstants.UTF_8);
        jsonFile.createNewFile();

//		List<WechatPayTran> wechatPayTrans = wechatPayPdfParser.parseTrans(pdfFilePath);
//		System.out.println(JsonUtils.convertObjectToJson(wechatPayTrans));
	}

}
